package com.myorigin.weblog.admin.config;

import com.myorigin.weblog.jwt.config.JwtAuthenticationSecurityConfig;
import com.myorigin.weblog.jwt.filter.TokenAuthenticationFilter;
import com.myorigin.weblog.jwt.handle.RestAccessDeniedHandler;
import com.myorigin.weblog.jwt.handle.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
/**
 * Spring Security 配置类
 * 应用 JWT 认证功能配置
 */
@Component
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)//启用方法级别的安全性设置
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationSecurityConfig jwtAuthenticationSecurityConfig;
    @Autowired
    private RestAuthenticationEntryPoint authEntryPoint;
    @Autowired
    private RestAccessDeniedHandler deniedHandler;

    /**
     * 一定记得配置注册好拦截器后才能正常拦截请求
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable() //前后端分离的情况下，通常不需要启用 CSRF 防护
                .formLogin().disable() //禁用表单登录
                .apply(jwtAuthenticationSecurityConfig) //设置用户登录认证相关配置
                .and()
                .authorizeRequests()
                .mvcMatchers("/admin/**").authenticated() //认证所有以/admin 为前缀的 URL 资源
                .anyRequest().permitAll()  //其他都需要放行，无需认证
                .and()
                .httpBasic().authenticationEntryPoint(authEntryPoint)//处理用户未登录访问受保护的资源情况!!!!!!!!!
                .and()
                .exceptionHandling().accessDeniedHandler(deniedHandler)//处理登录成功后访问受保护的资源，但是权限不够的情况!!!!!!!!
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)// 前后端分离，无需创建会话
                .and()
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);//将 Token 校验过滤器添加到用户认证过滤器之前!!!!!!
    }

    /**
     * Token 校验拦截器
     * @return
     */
    @Bean
    public TokenAuthenticationFilter tokenAuthenticationFilter(){
        return new TokenAuthenticationFilter();
    }
}
